home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / fax / src / recvfax / status.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  10KB  |  359 lines

  1. /*    $Header: /usr/people/sam/fax/recvfax/RCS/status.c,v 1.24 1994/04/04 18:25:18 sam Rel $
  2. /*
  3.  * Copyright (c) 1990, 1991, 1992, 1993, 1994 Sam Leffler
  4.  * Copyright (c) 1991, 1992, 1993, 1994 Silicon Graphics, Inc.
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and 
  7.  * its documentation for any purpose is hereby granted without fee, provided
  8.  * that (i) the above copyright notices and this permission notice appear in
  9.  * all copies of the software and related documentation, and (ii) the names of
  10.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  11.  * publicity relating to the software without the specific, prior written
  12.  * permission of Sam Leffler and Silicon Graphics.
  13.  * 
  14.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  15.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  16.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  17.  * 
  18.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  19.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  20.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  22.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  23.  * OF THIS SOFTWARE.
  24.  */
  25. #include "defs.h"
  26. #include "tiffio.h"
  27.  
  28. #include <fcntl.h>
  29. #include <sys/file.h>
  30. #include <sys/stat.h>
  31. #include <dirent.h>
  32. #include <errno.h>
  33.  
  34. static    void getConfig(char* fileName, config* configp, config* deflt);
  35. static    void getServerStatus(char* fileName, char buf[1024]);
  36.  
  37. void
  38. sendServerStatus(const char* modem, char* tag)
  39. {
  40.     DIR* dirp;
  41.     struct dirent* dentp;
  42.     config deflt;
  43.     char fifomatch[80];
  44.     int fifomatchlen;
  45.  
  46.     if (!(dirp = opendir("."))) {
  47.     syslog(LOG_ERR, "%s: opendir: %m", SPOOLDIR);
  48.     sendError("Problem accessing spool directory.");
  49.     done(-1, "EXIT");
  50.     }
  51.     /*
  52.      * Setup a prefix for matching potential FIFO files.
  53.      * We do this carefully and in a way that insures we
  54.      * use only the definitions in config.h.
  55.      */
  56.     if (strcmp(modem, MODEM_ANY) == 0)
  57.     modem = "";
  58.     sprintf(fifomatch, "%s.%.*s", FAX_FIFO,
  59.     sizeof (fifomatch) - (sizeof (FAX_FIFO)+2), modem);
  60.     fifomatchlen = strlen(fifomatch);
  61.     while ((dentp = readdir(dirp)) != 0) {
  62.     int fifo;
  63.  
  64.     if (strncmp(dentp->d_name, fifomatch, fifomatchlen) != 0)
  65.         continue;
  66.     fifo = open(dentp->d_name, O_WRONLY|O_NDELAY);
  67.     if (fifo != -1) {
  68.         config configuration;
  69.         char fileName[1024];
  70.         char* cp;
  71.  
  72.         (void) close(fifo);
  73.         cp = strchr(dentp->d_name, '.') + 1;
  74.         sprintf(fileName, "%s.%s", FAX_CONFIG, cp);
  75.         getConfig(fileName, &configuration, &deflt);
  76.         if (version > 0) {
  77.         char serverStatus[1024];
  78.         char* tp;
  79.  
  80.         sprintf(fileName, "%s/%s", FAX_STATUSDIR, cp);
  81.         getServerStatus(fileName, serverStatus);
  82.         /*
  83.          * Convert fifo name from canonical format back
  84.          * to a pathname by replacing '_'s with '/'s.
  85.          */
  86.         for (tp = cp; tp = strchr(tp, '_'); *tp = '/')
  87.             ;
  88.         sendClient("server", "%s:%s:%s",
  89.             configuration.faxNumber, cp, serverStatus);
  90.         } else
  91.         sendClient("server", "%s", configuration.faxNumber);
  92.     }
  93.     }
  94.     (void) closedir(dirp);
  95. }
  96.  
  97. static void
  98. sendClientJobStatus(Job* job, const char* jobname)
  99. {
  100.     if (version > 0) {
  101.     char tts[30];
  102.     if (job->tts != 0)
  103.         strftime(tts, sizeof (tts), "%Y/%m/%d %H.%M.%S",
  104.         localtime(&job->tts));
  105.     else
  106.         strcpy(tts, "asap");
  107.     sendClient("jobStatus", "%s:%s:%s:%s:%s:%s",
  108.         jobname, job->sender, tts, job->external, job->modem, job->status);
  109.     } else
  110.     sendClient("jobStatus", "%s:%s:%d:%s",
  111.         jobname, job->sender, job->tts, job->external);
  112. }
  113.  
  114. static void
  115. sendClientJobLocked(Job* job, const char* jobname)
  116. {
  117.     if (version > 0)
  118.     sendClient("jobStatus", "%s:%s:locked:%s:%s:%s",
  119.         jobname, job->sender, job->external, job->modem, job->status);
  120.     else
  121.     sendClient("jobLocked", "%s:%s:0:%s",
  122.         jobname, job->sender, job->external);
  123. }
  124.  
  125. void
  126. sendAllStatus(const char* modem, char* tag)
  127. {
  128.     Job* job;
  129.  
  130.     if (!jobList)
  131.     jobList = readJobs();
  132.     for(job = jobList; job; job = job->next) {
  133.     char *jobname = job->qfile+strlen(FAX_SENDDIR)+2;
  134.     if (!modemMatch(modem, job->modem))
  135.         continue;
  136.     if (job->flags & JOB_SENT)
  137.         continue;
  138.     job->flags |= JOB_SENT;
  139.     if (job->flags & JOB_LOCKED)
  140.         sendClientJobLocked(job, jobname);
  141.     else
  142.         sendClientJobStatus(job, jobname);
  143.     }
  144. }
  145.  
  146. void
  147. sendJobStatus(const char* modem, char* onwhat)
  148. {
  149.     Job* job;
  150.  
  151.     if (!jobList)
  152.     jobList = readJobs();
  153.     for(job = jobList; job; job = job->next) {
  154.     char *jobname = job->qfile+strlen(FAX_SENDDIR)+2;
  155.     if (!modemMatch(modem, job->modem))
  156.         continue;
  157.     if ((job->flags & JOB_SENT) || strcmp(jobname, onwhat) != 0)
  158.         continue;
  159.     job->flags |= JOB_SENT;
  160.     if (job->flags & JOB_LOCKED)
  161.         sendClientJobLocked(job, jobname);
  162.     else
  163.         sendClientJobStatus(job, jobname);
  164.     }
  165. }
  166.  
  167. void
  168. sendUserStatus(const char* modem, char* onwhat)
  169. {
  170.     Job* job;
  171.  
  172.     if (!jobList)
  173.     jobList = readJobs();
  174.     for(job = jobList; job; job = job->next) {
  175.     char *jobname = job->qfile+strlen(FAX_SENDDIR)+2;
  176.     if (!modemMatch(modem, job->modem))
  177.         continue;
  178.     if (job->flags & JOB_SENT)
  179.         continue;
  180.     if (job->flags & JOB_LOCKED) {
  181.         job->flags |= JOB_SENT;
  182.         sendClientJobLocked(job, jobname);
  183.     } else if (strcmp(job->sender, onwhat) == 0) {
  184.         job->flags |= JOB_SENT;
  185.         sendClientJobStatus(job, jobname);
  186.     }
  187.     }
  188. }
  189.  
  190. static int
  191. isFAXImage(TIFF* tif)
  192. {
  193.     u_short w;
  194.     if (TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &w) && w != 1)
  195.     return (0);
  196.     if (TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &w) && w != 1)
  197.     return (0);
  198.     if (!TIFFGetField(tif, TIFFTAG_COMPRESSION, &w) ||
  199.       (w != COMPRESSION_CCITTFAX3 && w != COMPRESSION_CCITTFAX4))
  200.     return (0);
  201.     if (!TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &w) ||
  202.       (w != PHOTOMETRIC_MINISWHITE && w != PHOTOMETRIC_MINISBLACK))
  203.     return (0);
  204.     return (1);
  205. }
  206.  
  207. static void
  208. sanitize(char* dst, const char* src, u_int maxlen)
  209. {
  210.     u_int i;
  211.     for (i = 0; i < maxlen-1 && src[i] != '\0'; i++)
  212.     dst[i] = (isascii(src[i]) && isprint(src[i]) ? src[i] : '?');
  213.     dst[i] = '\0';
  214. }
  215.  
  216. static int
  217. readQFile(int fd, char* qfile, int beingReceived, struct stat* sb)
  218. {
  219.     int ok = 0;
  220.     TIFF* tif = TIFFFdOpen(fd, qfile, "r");
  221.     if (tif) {
  222.     ok = isFAXImage(tif);
  223.     if (ok) {
  224.         u_long pageWidth, pageLength;
  225.         char* cp;
  226.         char sender[80];
  227.         char date[30];
  228.         float resolution = 98;
  229.         int c, i, npages;
  230.  
  231.         TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &pageWidth);
  232.         TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &pageLength);
  233.         if (TIFFGetField(tif, TIFFTAG_YRESOLUTION, &resolution)) {
  234.         u_short resunit = RESUNIT_NONE;
  235.         TIFFGetField(tif, TIFFTAG_RESOLUTIONUNIT, &resunit);
  236.         if (resunit == RESUNIT_CENTIMETER)
  237.             resolution *= 25.4;
  238.         } else
  239.         resolution = 98;
  240.         if (TIFFGetField(tif, TIFFTAG_IMAGEDESCRIPTION, &cp))
  241.         sanitize(sender, cp, sizeof (sender));
  242.         else
  243.         strcpy(sender, "<unknown>");
  244.         if (TIFFGetField(tif, TIFFTAG_DATETIME, &cp))
  245.         sanitize(date, cp, sizeof (date));
  246.         else
  247.         strftime(date, sizeof (date), "%Y:%m:%d %H:%M:%S",
  248.             localtime(&sb->st_mtime));
  249.         npages = 0;
  250.         do {
  251.         npages++;
  252.         } while (TIFFReadDirectory(tif));
  253.         if (version > 0)
  254.         sendClient("recvJob", "%d:%lu:%lu:%3.1f:%u:%s:%s",
  255.             beingReceived, pageWidth, pageLength, resolution,
  256.             npages, date, sender);
  257.         else
  258.         sendClient("recvJob", "%d:%lu:%lu:%3.1f:%u:%u:%s",
  259.             beingReceived, pageWidth, pageLength, resolution,
  260.             npages, sb->st_mtime, sender);
  261.     }
  262.     TIFFClose(tif);
  263.     }
  264.     return (ok);
  265. }
  266.  
  267. /*
  268.  * NB: received files must be opened with write access
  269.  * under svr4 because the flock emulation needs it.
  270.  */
  271. #if defined(svr4) || defined(hpux)
  272. #define    RECV_OMODE    O_RDWR
  273. #else
  274. #define    RECV_OMODE    O_RDONLY
  275. #endif
  276.  
  277. void
  278. sendRecvStatus(const char* modem, char* tag)
  279. {
  280.     DIR* dir = opendir(FAX_RECVDIR);
  281.     if (dir != NULL) {
  282.     struct dirent* dp;
  283.  
  284.     TIFFSetErrorHandler(NULL);
  285.     TIFFSetWarningHandler(NULL);
  286.     while (dp = readdir(dir)) {
  287.         char entry[1024];
  288.         struct stat sb;
  289.         int fd;
  290.  
  291.         if (strncmp(dp->d_name, "fax", 3) != 0)
  292.         continue;
  293.         sprintf(entry, "%s/%s", FAX_RECVDIR, dp->d_name);
  294.         if (stat(entry, &sb) < 0 || (sb.st_mode & S_IFMT) != S_IFREG)
  295.         continue;
  296.         fd = open(entry, RECV_OMODE);
  297.         if (fd > 0) {
  298.         int beingReceived =
  299.            (flock(fd, LOCK_EX|LOCK_NB) < 0 && errno == EWOULDBLOCK);
  300.         (void) readQFile(fd, entry, beingReceived, &sb);
  301.         close(fd);
  302.         }
  303.     }
  304.     closedir(dir);
  305.     } else
  306.     sendAndLogError("Can not access receive queue directory \"%s\".",
  307.         FAX_RECVDIR);
  308. }
  309.  
  310. static void
  311. getConfig(char* fileName, config* configp, config* deflt)
  312. {
  313.     char* cp;
  314.     FILE* configFile;
  315.     char configLine[1024];
  316.  
  317.     if (!configp)
  318.     return;
  319.     if (deflt) {
  320.     strcpy(configp->faxNumber, deflt->faxNumber);
  321.     } else {
  322.     configp->faxNumber[0] = '\0';
  323.     }
  324.     if (!fileName || !(configFile = fopen(fileName, "r")))
  325.     return;
  326.     while (fgets(configLine, sizeof (configLine)-1, configFile)) {
  327.     if (! (cp = strchr(configLine, '#')))
  328.         cp = strchr(configLine, '\n');
  329.     if (cp)
  330.         *cp = '\0';
  331.     if ((cp = strchr(configLine, ':')) != 0)
  332.         for (*cp++ = '\0'; isspace(*cp); cp++)
  333.         ;
  334.     else
  335.         continue;
  336.     if (strcasecmp(configLine, "FAXNumber") == 0) {
  337.         strcpy(configp->faxNumber, cp);
  338.         break;
  339.     }
  340.     }
  341.     (void) fclose(configFile);
  342. }
  343.  
  344. static void
  345. getServerStatus(char* fileName, char buf[1024])
  346. {
  347.     int fd = open(fileName, O_RDONLY);
  348.     if (fd > 0) {
  349.     int n;
  350.     flock(fd, LOCK_SH);
  351.     n = read(fd, buf, 1024-1);
  352.     buf[n] = '\0';
  353.     if (n > 0 && buf[n-1] == '\n')
  354.         buf[n-1] = '\0';
  355.     close(fd);
  356.     } else
  357.     strcpy(buf, "No status");
  358. }
  359.